"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _vue = require("vue");
var _xeUtils = _interopRequireDefault(require("xe-utils"));
var _core = require("@vxe-ui/core");
var _dom = require("../../ui/src/dom");
var _anchorLink = _interopRequireDefault(require("./anchor-link"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _default = exports.default = (0, _vue.defineComponent)({
  name: 'VxeAnchor',
  props: {
    modelValue: String,
    options: Array,
    container: [String, Object, Function],
    showMarker: {
      type: Boolean,
      default: true
    }
  },
  emits: ['update:modelValue', 'change', 'click'],
  setup(props, context) {
    const {
      slots,
      emit
    } = context;
    const xID = _xeUtils.default.uniqueId();
    const refElem = (0, _vue.ref)();
    const refMarkerElem = (0, _vue.ref)();
    const reactData = (0, _vue.reactive)({
      activeHref: null,
      staticLinks: [],
      containerElem: null
    });
    const refMaps = {
      refElem
    };
    const computeAllHrefList = (0, _vue.computed)(() => {
      const list = [];
      _xeUtils.default.eachTree(reactData.staticLinks, item => {
        list.push(item.href || '');
      }, {
        children: 'children'
      });
      return list;
    });
    const computeMaps = {};
    const $xeAnchor = {
      xID,
      props,
      context,
      reactData,
      getRefMaps: () => refMaps,
      getComputeMaps: () => computeMaps
    };
    const anchorMethods = {
      dispatchEvent(type, params, evnt) {
        emit(type, (0, _core.createEvent)(evnt, {
          $anchor: $xeAnchor
        }, params));
      }
    };
    const getContainerElem = () => {
      const {
        container
      } = props;
      if (container) {
        if (_xeUtils.default.isElement(container)) {
          return container;
        }
        if (_xeUtils.default.isString(container)) {
          return document.querySelector(container);
        }
        if (_xeUtils.default.isFunction(container)) {
          return container({
            $anchor: $xeAnchor
          });
        }
      }
      return null;
    };
    const emitEvent = value => {
      reactData.activeHref = value;
      emit('update:modelValue', value);
    };
    const handleContainerScrollEvent = () => {
      const allHrefList = computeAllHrefList.value;
      const {
        containerElem
      } = reactData;
      if (containerElem) {
        const wrapperElList = containerElem.querySelectorAll(allHrefList.map(href => `${href}`).join(','));
        for (let i = 0; i < wrapperElList.length; i++) {
          const wrapperEl = wrapperElList[i];
          const wrapperRect = wrapperEl.getBoundingClientRect();
          if (wrapperRect.top > 0) {
            const href = wrapperEl.id;
            reactData.activeHref = `#${href}`;
            break;
          }
        }
      }
    };
    const removeContainerElemScroll = () => {
      const {
        containerElem
      } = reactData;
      if (containerElem) {
        containerElem.removeEventListener('scroll', handleContainerScrollEvent);
      }
    };
    const updateContainerElem = () => {
      const containerElem = getContainerElem();
      reactData.containerElem = containerElem;
      if (containerElem) {
        containerElem.addEventListener('scroll', handleContainerScrollEvent, {
          passive: false
        });
      }
    };
    const updateMarkerPos = () => {
      (0, _vue.nextTick)(() => {
        const {
          activeHref
        } = reactData;
        const elem = refElem.value;
        const markerEl = refMarkerElem.value;
        if (elem && markerEl) {
          if (activeHref) {
            const linkEl = elem.querySelector(`[href="${activeHref}"]`);
            if (linkEl) {
              const {
                top
              } = (0, _dom.getOffsetPos)(linkEl, elem);
              markerEl.style.top = `${top}px`;
            }
          }
        }
      });
    };
    const anchorPrivateMethods = {
      handleClickLink(evnt, href) {
        evnt.preventDefault();
        const targetEl = document.getElementById(`${href}`.replace('#', ''));
        if (targetEl) {
          targetEl.scrollIntoView({
            behavior: 'smooth'
          });
        }
        emitEvent(href);
        anchorMethods.dispatchEvent('click', {
          href
        }, evnt);
      }
    };
    Object.assign($xeAnchor, anchorMethods, anchorPrivateMethods);
    const renderSubItems = options => {
      const itemVNs = [];
      if (options) {
        options.forEach(item => {
          const subItems = item.children;
          if (subItems && subItems.length) {
            itemVNs.push((0, _vue.h)(_anchorLink.default, {
              content: item.content,
              title: item.title,
              href: item.href
            }, {
              sub: () => renderSubItems(subItems)
            }));
          } else {
            itemVNs.push((0, _vue.h)(_anchorLink.default, {
              content: item.content,
              title: item.title,
              href: item.href
            }));
          }
        });
      }
      return itemVNs;
    };
    const renderVN = () => {
      const {
        options,
        showMarker
      } = props;
      const defaultSlot = slots.default;
      return (0, _vue.h)('div', {
        ref: refElem,
        class: ['vxe-anchor', {
          'is--marker': showMarker
        }]
      }, [(0, _vue.h)('div', {
        class: 'vxe-anchor--list'
      }, defaultSlot ? defaultSlot({}) : renderSubItems(options)), showMarker ? (0, _vue.h)('div', {
        ref: refMarkerElem,
        class: 'vxe-anchor--marker'
      }) : (0, _vue.createCommentVNode)()]);
    };
    (0, _vue.watch)(() => props.modelValue, val => {
      reactData.activeHref = val;
    });
    (0, _vue.watch)(() => reactData.activeHref, () => {
      updateMarkerPos();
    });
    (0, _vue.watch)(() => props.container, () => {
      removeContainerElemScroll();
      updateContainerElem();
    });
    (0, _vue.onMounted)(() => {
      (0, _vue.nextTick)(() => {
        updateContainerElem();
      });
    });
    (0, _vue.onBeforeUnmount)(() => {
      removeContainerElemScroll();
    });
    (0, _vue.provide)('$xeAnchor', $xeAnchor);
    $xeAnchor.renderVN = renderVN;
    return $xeAnchor;
  },
  render() {
    return this.renderVN();
  }
});